﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using DevExpress.XtraEditors;
using DevExpress.XtraGrid.Views.Grid;
using ProgNetComponentsDx.Enums;
using DevExpress.XtraGrid;
using ProgNetComponentsDx.Data;
using System.Drawing.Design;
using ProgNetComponents.Classes;
using ProgNetComponents.Data;
using DevExpress.XtraGrid.Views.Base;


namespace ProgNetComponentsDx.Forms
{
    public partial class BaseSqlCeForm : XtraForm
    {
        protected string ValidationMessage;
        protected virtual string MainTable
        {
            get
            {
                string str = "";
                SelectData data = SelectDataCache.GetSelectData(selectDataProvider1.GetSettings(this).SelectDataId);
                if (data != null && data.RecordSelect.Count > 0)
                    str = data.RecordSelect[0].DataSetTableName;
                return str;
            }
        }
        protected virtual DataRow MainRow
        {
            get
            {
                DataRow row = null;
                if (MainTable.IsNotNull())
                {
                    if (selectDataProvider1.GetSettings(this).DataSet != null &&
                        selectDataProvider1.GetSettings(this).DataSet.Tables.Contains(MainTable) &&
                        selectDataProvider1.GetSettings(this).DataSet.Tables[MainTable].Rows.Count > 0)
                        row = selectDataProvider1.GetSettings(this).DataSet.Tables[MainTable].Rows[0];
                }
                return row;
            }
        }
        protected object CurrentRecord
        {
            get;
            set;
        }
        private string baseText;

        [Editor(typeof(ProgNetComponents.Design.Editors.ColumnNameEditor), typeof(UITypeEditor))]
        [Category(ProgNetComponents.Constants.Categories.ProgNetSettings)]
        public string NameColumn
        {
            get;
            set;
        }

        [Editor(typeof(ProgNetComponentsDx.Browsers.Design.Editors.BrowserNameEditor), typeof(UITypeEditor))]
        [Category(ProgNetComponents.Constants.Categories.ProgNetSettings)]
        public object BrowserId
        {
            get;
            set;
        }

        [Category(ProgNetComponents.Constants.Categories.ProgNetSettings)]
        public bool ShouldUpdateMdiHelper
        {
            get;
            set;
        }
        public BaseSqlCeForm()
        {
            InitializeComponent();
            ShouldUpdateMdiHelper = true;
        }

        public BaseSqlCeForm(object value)
        {
            InitializeComponent();
            CurrentRecord = value;
            ShouldUpdateMdiHelper = true;
        }

        protected virtual bool Save()
        {
            return selectDataProvider1.UpdateDataSet();
        }
        protected virtual void FinishEdit()
        {
            if (modeProvider1.CurrentMode == FormMode.Read ||
               modeProvider1.CurrentMode == FormMode.View)
                return;

            if (this.ActiveControl != null)
            {
                try
                {
                    BaseView v = null;
                    if (this.ActiveControl is GridControl)
                    {
                        v = ((GridControl)(this.ActiveControl)).FocusedView;
                    }
                    else if (this.ActiveControl.Parent is GridControl)
                    {
                        v = ((GridControl)(this.ActiveControl.Parent)).FocusedView;
                    }
                    else if (this.ActiveControl.Parent != null && this.ActiveControl.Parent.Parent is GridControl)
                    {
                        v = ((GridControl)(this.ActiveControl.Parent.Parent)).FocusedView;
                    }
                    if (v != null)
                        v.CloseEditor();
                    if (v != null)
                        v.UpdateCurrentRow();
                }
                catch { }

                this.SelectNextControl(this.ActiveControl, true, true, false, true);
                this.SelectNextControl(this.ActiveControl, false, true, false, true);
                UpdateDataSource();
            }
        }
        protected virtual void UpdateDataSource()
        {
            try
            {
                BindingContext.EndCurrentEdit();
            }
            catch { }
        }
        protected virtual void UpdateControlsFromDataSource()
        {
            try
            {
                this.ReadValuesFromBindings();
            }
            catch { }
        }

        protected virtual void OpenClick(bool afterDelete = false)
        {
            if (BrowserId.IsNotNull())
            {
                if (modeProvider1.CurrentMode!= FormMode.Read &&
                    modeProvider1.CurrentMode != FormMode.View)
                    EditClick();
                if (modeProvider1.CurrentMode == FormMode.Read ||
                    modeProvider1.CurrentMode == FormMode.View)
                {
                    ObjectDialogResult dlg = browserProvider1.GetBrowser(BrowserId).ShowNewDialog();
                    if (dlg.DialogResult == System.Windows.Forms.DialogResult.OK)
                    {
                        CurrentRecord = dlg.Value;
                        UpdateMdiChild();
                        GetRecord();
                    }
                    else
                    {
                        if (afterDelete)
                        {
                            Close();
                        }
                    }
                }
            }
        }

        protected virtual void UpdateMdiChild()
        {
            if (ShouldUpdateMdiHelper && ProgNetComponents.MDI.MdiHelper.Instance != null)
            {
                ProgNetComponents.MDI.MdiHelper.Instance.AddOrUpdateChild(this, CurrentRecord);
            }
        }
        protected virtual void AddClick()
        {
            if (modeProvider1.CurrentMode != FormMode.Read &&
                    modeProvider1.CurrentMode != FormMode.View)
                EditClick();
            if (modeProvider1.CurrentMode == FormMode.Read ||
                modeProvider1.CurrentMode == FormMode.View)
            {
                CurrentRecord = null;
                GetRecord();
            }
        }
        protected virtual void KopiujClick()
        {
            if (modeProvider1.CurrentMode != FormMode.Read &&
                    modeProvider1.CurrentMode != FormMode.View)
                EditClick();
            if (modeProvider1.CurrentMode == FormMode.Read ||
                modeProvider1.CurrentMode == FormMode.View)
            {
                CurrentRecord = null;
                CopyRecord();
                modeProvider1.CurrentMode = FormMode.New;
            }
        }
        protected virtual void CopyRecord()
        {
            DataColumn autoIncCol = null;
            DataRow tmpRow;
            foreach (DataTable dt in selectDataProvider1.GetSettings(this).DataSet.Tables)
            {
                autoIncCol = null;
                foreach (DataColumn c in dt.Columns)
                {
                    if (c.AutoIncrement)
                    {
                        autoIncCol = c;
                        break;
                    }
                }
                foreach (DataRow r in dt.Rows)
                {
                    r.SetAdded();
                    if (autoIncCol != null)
                    {
                        tmpRow = dt.NewRow();
                        r[autoIncCol] = tmpRow[autoIncCol];
                        tmpRow.Delete();
                    }
                }
            }
            changeDetectorProvider1.SetModified();
        }
        
        protected virtual void DeleteClick()
        {
            if (MainRow!= null && CanDeleteRow(MainRow))
            {
                if (DeletePrompt() == System.Windows.Forms.DialogResult.Yes)
                {
                    MainRow.Delete();
                    if (selectDataProvider1.UpdateDataSet())
                    {
                        OpenClick(true);
                    }
                    else
                    {
                        this.ShowDxErrorDialog("Błąd kasowania rekordu!");
                    }
                }
            }
            else
            {
                this.ShowDxInfoDialog("Rekord jest używany. Nie można go skasować.");
            }
        }
        protected virtual bool CanDeleteRow(DataRow row)
        {
            if (row !=null && row.RowState == DataRowState.Added)
                return true;
            DataManager m = SelectDataCache.GetManager(selectDataProvider1.GetSettings(this).SelectDataId);
            if (m != null)
                return !m.SchemaChecker.IsRecordUsed(row);
            return true;
        }

        protected virtual DialogResult DeletePrompt()
        {
            return this.ShowDxYNQuestionDialog("Napewno chcesz skasować rekord?");
        }

        protected virtual void SaveClick()
        {
            if (ValidateAll())
            {
                if (Save())
                {
                    if (modeProvider1.CurrentMode == FormMode.New)
                    {
                        UpdateCurrentRecordAfterSave();
                        UpdateMdiChild();
                    }
                    modeProvider1.CurrentMode = FormMode.Read;
                    changeDetectorProvider1.ResetAll();
                }
                else
                {
                    this.ShowDxErrorDialog("Błąd zapisu!");
                }
            }
            else
            {
                if (ValidationMessage.IsNull())
                    ValidationMessage = "Błąd validacji.";

                this.ShowDxErrorDialog(ValidationMessage);
            }
        }
        protected virtual void UpdateCurrentRecordAfterSave()
        {
            string col = "";
            if (MainRow != null)
            {
                if (MainRow.Table.PrimaryKey.Length == 1)
                    col = MainRow.Table.PrimaryKey[0].ColumnName;
                else
                {
                    foreach (DataColumn c in MainRow.Table.Columns)
                    {
                        if (c.AutoIncrement)
                        {
                            col = c.ColumnName;
                            break;
                        }
                    }
                }
            }
            if (col.IsNotNullOrEmpty() && MainRow!=null)
            {
                CurrentRecord = MainRow[col];
            }
        }
        protected virtual void EditClick()
        {
            if (modeProvider1.CurrentMode == FormMode.Read)
            {
                modeProvider1.CurrentMode = FormMode.Edit;
            }
            else
            {
                if (changeDetectorProvider1.HasChanges)
                {
                    DialogResult res = this.ShowDxYNCQuestionDialog("Zapisać zmiany?");
                    if (res == System.Windows.Forms.DialogResult.No)
                    {
                        selectDataProvider1.GetSettings(this).DataSet.RejectChanges();
                        modeProvider1.CurrentMode = FormMode.Read;
                        changeDetectorProvider1.ResetAll();
                    }
                    else if (res == System.Windows.Forms.DialogResult.Yes)
                    {
                        FinishEdit();
                        SaveClick();
                    }
                }
                else
                {
                    modeProvider1.CurrentMode = FormMode.Read;
                }
            }
        }
        protected virtual void RefreshClick()
        {
            if (!GetRecord())
                this.ShowDxErrorDialog("Błąd czytania danych!");
        }
        protected virtual bool ValidateAll()
        {
            bool result = false;
            ValidationMessage = "";
            result = modeProvider1.ValidateRequiredColumns(ref ValidationMessage) &&
                modeProvider1.ValidateRequiredEdits(ref ValidationMessage);
            return result;
        }
        protected virtual void OnContextChanged()
        {
            if (!this.IsDesignMode())
            {
                if (changeDetectorProvider1.HasChanges)
                {
                    Text = GetText() + " *";
                    modeProvider1.GetSettings(bbiSave).ReadOnlyModes = FormMode.Read | FormMode.View;
                }
                else
                {
                    Text = GetText();
                    modeProvider1.GetSettings(bbiSave).ReadOnlyModes = FormMode.All;
                }
            }
        }

        protected virtual bool GetRecord()
        {
            bool result = false;
            if (CurrentRecord.IsNull())
            {
                result = NewRecord();
                if (MainRow != null)
                {
                    MainRow.BeginEdit();
                    UpdateDataSource();
                    MainRow.EndEdit();
                }
            }
            else
            {
                FillParams();
                result = selectDataProvider1.FillDataSet();
            }
            if (result)
            {
                UpdateControlsFromDataSource();
                changeDetectorProvider1.ResetAll();
                if (modeProvider1.CurrentMode == FormMode.New)
                    changeDetectorProvider1.SetModified();
            }
            return result;
        }

        protected virtual string GetText()
        {
            if(MainRow!=null && NameColumn.IsNotNull() &&
                MainRow.Table.Columns.Contains(NameColumn) && 
                MainRow.RowState!= DataRowState.Added)
                return baseText + " [" + MainRow[NameColumn].AsString() + "]";
            return baseText;
        }

        protected virtual bool NewRecord()
        {
            if (MainTable.IsNotNull())
            {
                if (selectDataProvider1.GetSettings(this).DataSet != null &&
                    selectDataProvider1.GetSettings(this).DataSet.Tables.Contains(MainTable))
                {
                     selectDataProvider1.GetSettings(this).DataSet.Clear();
                     selectDataProvider1.GetSettings(this).DataSet.AcceptChanges();
                     DataRow row = selectDataProvider1.GetSettings(this).DataSet.Tables[MainTable].NewRow();
                     selectDataProvider1.GetSettings(this).DataSet.Tables[MainTable].Rows.Add(row);
                     modeProvider1.CurrentMode = FormMode.New;
                     changeDetectorProvider1.SetModified();
                     return true;
                }
            }
            return false;
        }

        protected virtual void FillParams()
        {
            if (CurrentRecord != null)
            {
                if (CurrentRecord.GetType() == typeof(object[]))
                {
                    for (int i=0; i < ((Array)(CurrentRecord)).Length; i++)
                    {
                        selectDataProvider1.GetSettings(this).Parameters[i].Value = (CurrentRecord as object[])[i];
                    }
                }
                else
                {
                    selectDataProvider1.GetSettings(this).Parameters[0].Value = CurrentRecord;
                }
            }
        }

        protected virtual void OnLoad()
        {
            if (!GetRecord())
            {
                this.ShowDxErrorDialog("Błąd czytania danych!");
                modeProvider1.CurrentMode = FormMode.View;
                return;
            }
            if (AutoLoadLayout)
                layoutProvider1.ApplySavedLayout();
            if (modeProvider1.CurrentMode != FormMode.New)
                modeProvider1.CurrentMode = FormMode.Edit;
        }

        protected virtual bool AutoSaveLayout
        {
            get { return layoutProvider1.HasLayouts && bbiAutoLayout.Checked; }
        }
        protected virtual bool AutoLoadLayout
        {
            get { return true; }
        }
        private void bbiRefresh_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            RefreshClick();
        }

        private void bbiSave_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            FinishEdit();
            SaveClick();
        }

        private void bbiEdit_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            FinishEdit();
            EditClick();
        }

        private void bbiOtworz_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            OpenClick();
        }

        private void bbiDodaj_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            AddClick();
        }

        private void bbiUsun_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            DeleteClick();
        }

        private void changeDetectorProvider1_ContextChanged(object sender, EventArgs e)
        {
            OnContextChanged();
        }

        private void BaseSqlCeForm_Load(object sender, EventArgs e)
        {
            baseText = this.Text;
			if(this.IsDesignMode())
			{
				if (layoutProvider1.LayoutName.IsNull())
					layoutProvider1.LayoutName = this.Site.Name;
            } 
			else
				OnLoad();
        }

        private void bbiZapiszLayout_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            layoutProvider1.SaveLayout();
        }

        private void bbiResetLayout_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            layoutProvider1.RestoreDefaultLayout();
        }

        private void bbiReadLayout_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            layoutProvider1.ApplySavedLayout();
        }

        protected override void OnFormClosed(FormClosedEventArgs e)
        {
			if(!this.IsDesignMode())
			{
				if (AutoSaveLayout)
					layoutProvider1.SaveLayout();
				base.OnFormClosed(e);
			}
        }

        private void bbiKopiuj_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            KopiujClick();
        }

        
    }
}
